package icu.zqyhdm.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.zqyhdm.blog.constant.RedisConst;
import icu.zqyhdm.blog.entity.*;
import icu.zqyhdm.blog.mapper.*;
import icu.zqyhdm.blog.openFeign.CommonServiceFeignClient;
import icu.zqyhdm.blog.vo.*;
import icu.zqyhdm.blog.service.*;
import icu.zqyhdm.exception.MyException;
import icu.zqyhdm.helper.JwtHelper;
import icu.zqyhdm.result.Result;
import icu.zqyhdm.result.ResultCodeEnum;
import icu.zqyhdm.utils.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author lifu
 * @Date 2021/6/23 9:40
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private TypeMapper typeMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private CommonServiceFeignClient commonServiceFeignClient;

    /**
     * 注册
     */
    @Override
    public void register(UserRegisterVo userRegisterVo) {
        //userRegisterVo获取输入的手机号和验证码
        String phone = userRegisterVo.getPhone();
        String code = userRegisterVo.getCode();
        //判断验证码是否一致
        String redisCode = redisTemplate.opsForValue().get(phone);
        if(!code.equals(redisCode)){
            throw new MyException(ResultCodeEnum.CODE_ERROR);
        }
        //判断是否是第一次登录，数据库中是否存在手机号
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        User user = baseMapper.selectOne(wrapper);
        if(user == null){
            //添加信息到数据库
            user = new User();
            user.setPhone(phone);
            user.setNickName(userRegisterVo.getNickName());
            user.setPassword(MD5.encrypt(userRegisterVo.getPassword()));
            baseMapper.insert(user);
        }else {
            throw new MyException(ResultCodeEnum.REGISTER_ERROR);
        }
    }

    /**
     * 手机登录
     */
    @Override
    public String phoneLogin(UserPhoneLoginVo userPhoneLoginVo) {
        //获取输入的手机号和密码
        String phone = userPhoneLoginVo.getPhone();
        String code = userPhoneLoginVo.getCode();
        //判断验证码是否一致
        String redisCode = redisTemplate.opsForValue().get(phone);
        if(!code.equals(redisCode)){
            throw new MyException(ResultCodeEnum.CODE_ERROR);
        }
        // 判断是否是第一次登录
        User user = baseMapper.selectOne(new QueryWrapper<User>()
                .eq("phone",phone));
        if(user == null){
            // 第一次登录，先注册用户信息，默认用手机号当作昵称，再返回token
            User newUser = new User();
            newUser.setPhone(phone);
            newUser.setNickName(phone);
            baseMapper.insert(newUser);
            return JwtHelper.createToken(newUser.getId(),newUser.getNickName());
        }else {
            // 返回token并更新登录时间
            updateLoginTime(user);
            return JwtHelper.createToken(user.getId(),user.getNickName());
        }
    }

    /**
     * 账号密码登录
     */
    @Override
    public String accountLogin(UserAccountLoginVo userAccountLoginVo,HttpServletRequest request) {
        //获取输入的手机号和密码
        String phone = userAccountLoginVo.getPhone();
        String code = userAccountLoginVo.getCode();
        String password = userAccountLoginVo.getPassword();

        // 验证验证码是否正确
//        String captchaCode = (String) request.getSession().getAttribute("captchaCode");
//        request.getSession().removeAttribute("captchaCode");
//        if (!captchaCode.equals(code) {
//            throw new MyException(ResultCodeEnum.CODE_ERROR);
//        }
        // 验证密码
        User user = baseMapper.selectOne(new QueryWrapper<User>()
                .eq("phone",phone));
        if(user == null){
            throw new MyException(ResultCodeEnum.USER_EXIST_ERROR);
        }
        if(!MD5.encrypt(password).equals(user.getPassword())){
            throw new MyException(ResultCodeEnum.LOGIN_ERROR);
        }
        // 返回token并更新登录时间
        updateLoginTime(user);
        return JwtHelper.createToken(user.getId(),user.getNickName());
    }

    //异步更新用户登录时间
    @Async
    public void updateLoginTime(User user){
        user.setLoginTime(new Date());
        baseMapper.updateById(user);
    }

    /**
     * 发送注册的手机验证码
     */
    @Override
    public void send(String phone) {
        // 调用短信发送服务接口
        String resultString = commonServiceFeignClient.sendCode(phone);
        Result result = JSON.parseObject(resultString, Result.class);
        String code = result.getData().toString();
        if(code == null){
            throw new MyException(ResultCodeEnum.MESSAGE_ERROR);
        }
        //将验证码存放到redis
        redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
    }

    //根据id查询用户的详情信息
    @Override
    @Cacheable(value = "blog:userInfo",key = "#userId")
    public UserDetailVo getUserDetail(Integer userId) {
        User user = baseMapper.selectById(userId);
        // 封装用户信息
        Integer articleCount = articleMapper.selectCount(new QueryWrapper<Article>()
                .eq("author_id", userId));
        // 文章类型数量
        Integer typeCount = typeMapper.selectCount(new QueryWrapper<Type>()
                .eq("author_id",userId));
        // 文章标签数量
        Integer tagCount = tagMapper.selectCount(new QueryWrapper<Tag>()
                .eq("author_id",userId));
        UserDetailVo userDetailVo = UserDetailVo.builder()
                .id(user.getId())
                .nickName(user.getNickName())
                .img(user.getImg())
                .autograph(user.getAutograph())
                .email(user.getEmail())
                .articleNum(articleCount)
                .typeNum(typeCount)
                .tagNum(tagCount)
                .build();
        return userDetailVo;
    }

    @Override
    public Map<String, String> adminLogin(AdminLoginVo adminLoginVoLoginVo) {
        String phone = adminLoginVoLoginVo.getUsername();
        String password = adminLoginVoLoginVo.getPassword();
        User user = baseMapper.selectOne(new QueryWrapper<User>()
                .eq("phone",phone));
        Map<String,String> map = new HashMap<>();
        map.put("token",JwtHelper.createToken(user.getId(),user.getNickName()));
        return map;
    }

}
